////////////////////////////////////////////////////////////////////////////
//
//  Crytek Engine Source File.
//  Copyright (C), Crytek Studios, 2001.
// -------------------------------------------------------------------------
//  File name:   TagPoint.cpp
//  Version:     v1.00
//  Created:     10/10/2001 by Timur.
//  Compilers:   Visual C++ 6.0
//  Description: CTagPoint implementation.
// -------------------------------------------------------------------------
//  History:
//
////////////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "TagPoint.h"
#include <IAgent.h>

#include "..\Viewport.h"

#include <IAISystem.h>
#include "..\AI\AIManager.h"
#include "SegmentedWorld/SegmentedWorldManager.h"

//////////////////////////////////////////////////////////////////////////
// CBase implementation.
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CTagPoint,CEntityObject)
IMPLEMENT_DYNCREATE(CRespawnPoint,CTagPoint)
IMPLEMENT_DYNCREATE(CSpawnPoint,CTagPoint)
IMPLEMENT_DYNCREATE(CNavigationSeedPoint,CTagPoint)
IMPLEMENT_DYNCREATE(C3DNavVolumeSeed,CTagPoint)

#define TAGPOINT_RADIUS 0.5f

//////////////////////////////////////////////////////////////////////////
float CTagPoint::m_helperScale = 1;

//////////////////////////////////////////////////////////////////////////
CTagPoint::CTagPoint()
{
	m_entityClass = "TagPoint";
}

//////////////////////////////////////////////////////////////////////////
bool CTagPoint::Init( IEditor *ie,CBaseObject *prev,const CString &file )
{
	SetColor( RGB(0,0,255) );
	bool res = CEntityObject::Init( ie,prev,file );

	// Entity can overwrite icon.
	SetTextureIcon( GetClassDesc()->GetTextureIconId() );
	UseMaterialLayersMask(false);
	
	return res;
}

//////////////////////////////////////////////////////////////////////////
float CTagPoint::GetRadius()
{
	return TAGPOINT_RADIUS * m_helperScale * gSettings.gizmo.helpersScale;
}

//////////////////////////////////////////////////////////////////////////
void CTagPoint::BeginEditParams( IEditor *ie,int flags )
{
	__super::BeginEditParams( ie,flags );
}

//////////////////////////////////////////////////////////////////////////
void CTagPoint::EndEditParams( IEditor *ie )
{
	__super::EndEditParams( ie );
}

//////////////////////////////////////////////////////////////////////////
int CTagPoint::MouseCreateCallback( CViewport *view,EMouseEvent event,CPoint &point,int flags )
{
	if (event == eMouseMove || event == eMouseLDown)
	{
		Vec3 pos;
		if (GetIEditor()->GetAxisConstrains() != AXIS_TERRAIN)
		{
			pos = view->MapViewToCP(point);
		}
		else
		{
			// Snap to terrain.
			bool hitTerrain;
			pos = view->ViewToWorld( point,&hitTerrain );
			if (hitTerrain)
			{
				pos.z = GetIEditor()->GetTerrainElevation(pos.x,pos.y) + 1.0f;
			}
			pos = view->SnapToGrid(pos);
		}

		pos = view->SnapToGrid(pos);
		SetPos( pos );
		if (event == eMouseLDown) {
			SW_TEST_OBJ_PLACETO_MCB(GetPos(), GetLayer(), true);
			SW_ON_OBJ_NEW(this);
			return MOUSECREATE_OK;
		}
		return MOUSECREATE_CONTINUE;
	}
	return CBaseObject::MouseCreateCallback( view,event,point,flags );
}

//////////////////////////////////////////////////////////////////////////
void CTagPoint::Display( DisplayContext &dc )
{
	const Matrix34 &wtm = GetWorldTM();

	float fHelperScale = 1*m_helperScale*gSettings.gizmo.helpersScale;
	Vec3 dir = wtm.TransformVector( Vec3(0,fHelperScale,0) );
	Vec3 wp = wtm.GetTranslation();
	if (IsFrozen())
		dc.SetFreezeColor();
	else
		dc.SetColor( 1, 1, 0 );
	dc.DrawArrow( wp,wp+dir*2,fHelperScale );

	if (IsFrozen())
		dc.SetFreezeColor();
	else
		dc.SetColor( GetColor(),0.8f );

	dc.DrawBall( wp,GetRadius() );

	if (IsSelected())
	{
		dc.SetSelectedColor(0.6f);
		dc.DrawBall( wp,GetRadius()+0.02f );
	}

	// Entity can overwrite icon.
//	SetTextureIcon( GetClassDesc()->GetTextureIconId() );
	DrawDefault( dc );
}

//////////////////////////////////////////////////////////////////////////
bool CTagPoint::HitTest( HitContext &hc )
{
	// Must use icon..

	Vec3 origin = GetWorldPos();
	float radius = GetRadius();

	Vec3 w = origin - hc.raySrc;
	Vec3 wcross = hc.rayDir.Cross( w );
	float d = wcross.GetLengthSquared();

	if (d < radius*radius + hc.distanceTolerance &&
			w.GetLengthSquared() > radius*radius)           // Check if we inside TagPoint, then do not select!
	{
		Vec3 i0;
		if (Intersect::Ray_SphereFirst(Ray(hc.raySrc,hc.rayDir),Sphere(origin,radius),i0))
		{
			hc.dist = hc.raySrc.GetDistance(i0);
			return true;
		}
		hc.dist = hc.raySrc.GetDistance(origin);
		return true;
	}

	return false;
}

//////////////////////////////////////////////////////////////////////////
void CTagPoint::GetBoundBox( AABB &box )
{
	Vec3 pos = GetWorldPos();
	float r = GetRadius();
	box.min = pos - Vec3(r,r,r);
	box.max = pos + Vec3(r,r,r);
}

//////////////////////////////////////////////////////////////////////////
void CTagPoint::GetLocalBounds( AABB &box )
{
	float r = GetRadius();
	box.min = -Vec3(r,r,r);
	box.max = Vec3(r,r,r);
}

//////////////////////////////////////////////////////////////////////////
void CTagPoint::SetHelperScale( float scale )
{ 
	if(m_helperScale != scale)
	{
		SW_ON_OBJ_MOD(this);
	}
	m_helperScale = scale;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
CRespawnPoint::CRespawnPoint()
{
	m_entityClass = "RespawnPoint";
}

CSpawnPoint::CSpawnPoint()
{
	m_entityClass = "SpawnPoint";
}

//////////////////////////////////////////////////////////////////////////
CNavigationSeedPoint::CNavigationSeedPoint()
{
	m_entityClass = "NavigationSeedPoint";
}

void CNavigationSeedPoint::Display( DisplayContext &dc )
{
	DrawDefault( dc );
}

int CNavigationSeedPoint::MouseCreateCallback( CViewport *view,EMouseEvent event,CPoint &point,int flags )
{
	const int retValue = __super::MouseCreateCallback(view, event, point, flags);

	if (event == eMouseLDown)
	{
		GetIEditor()->GetAI()->CalculateNavigationAccessibility();
	}

	return retValue;
}

void CNavigationSeedPoint::Done()
{
	__super::Done();
	GetIEditor()->GetAI()->CalculateNavigationAccessibility();
}

void CNavigationSeedPoint::SetModified(bool boModifiedTransformOnly)
{
	__super::SetModified(boModifiedTransformOnly);
	GetIEditor()->GetAI()->CalculateNavigationAccessibility();
}


////////////////////////////////////////////////////////////////////////////
C3DNavVolumeSeed::C3DNavVolumeSeed()
{
	m_entityClass = "NavVolumeSeed";
}

/////////////////////////////////////////////////////////////////////////////////////

bool C3DNavVolumeSeed::Init( IEditor *ie,CBaseObject *prev,const CString &file )
{
	bool res = CTagPoint::Init( ie,prev,file );
	SetColor( RGB(255,128,128) );

	return res;
}

void C3DNavVolumeSeed::Display( DisplayContext &dc )
{
	const Matrix34 &wtm = GetWorldTM();

	float fHelperScale = 1*m_helperScale*gSettings.gizmo.helpersScale;
	//	Vec3 dir = wtm.TransformVector( Vec3(0,fHelperScale,0) );
	Vec3 wp = wtm.GetTranslation();
	//dc.SetColor( 1,1,0 );
	//dc.DrawArrow( wp,wp+dir*2,fHelperScale );

	if (IsFrozen())
		dc.SetFreezeColor();
	else
	{
		dc.SetColor( GetColor(),1.f );
	}

	dc.DrawBall( wp,GetRadius() );
	dc.DrawWireSphere(wp,GetRadius()*1.5f);

	if (IsSelected())
	{
		dc.SetSelectedColor(0.6f);
		dc.DrawBall( wp,GetRadius()*1.1f );
		dc.DrawWireSphere(wp,GetRadius()*1.1f*1.5f);
	}
	DrawDefault( dc );
}
